In [1]:
## 사전실행코드
import polars as pl
import plotly.express as px
## plotly가 주피터 노트북, 주피터 랩에서 표시되지 않는 경우 아래의 코드를 실행시키세요
import plotly.io as pio
pio.renderers.default = "notebook_connected"

df_spotify = (pl.read_csv("./universal_top_spotify_songs.csv", try_parse_dates = True,
null_values = [""])
    .filter(pl.col('snapshot_date').dt.year() == 2024).sort('snapshot_date'))

df_spotify = (
    df_spotify.with_columns(pl.when(pl.col('country').is_null() == True) ## country 열이 null이면
        .then(pl.lit('WW')) ## WW로 변경
        .otherwise(pl.col('country')).alias('country')) ## 아니면 원래대로
    .drop_nulls()) ## 그 외 null이 들어간 행 삭제

key_levels = pl.Enum(["C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B"])

df_spotify = (df_spotify.with_columns(pl.col('key').cast(pl.String)
    .replace(["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"],
        ["C", "C#", "D", "Eb", "E", "F", "F#", "G", "G#", "A", "Bb", "B"]))
    .with_columns(pl.col('key').cast(key_levels)).sort('key'))

df_spotify = (df_spotify.with_columns(pl.col('artists').str.split(', ')) ## ,를 기준으로 문자열을 분리
    ## 리스트의 첫 번째 아이템을 가져와서 main_vocal로 저장
    .with_columns(pl.col('artists').list.get(0, null_on_oob = True).alias('main_vocal'),
        pl.col('artists').list.tail(-1).alias('featuring')) ## 첫 번째 아이템을 제외한 나머지를featuring으로 저장
    .with_columns(pl.when(pl.col('featuring').list.len() == 0) ## 리스트 길이가 0이면
        .then(None) ## None으로 설정
        .otherwise(pl.col('featuring')).name.keep())) ## 아니면 그대로 유지

import pycountry_convert as pc

def get_continent_name(nation_code: str) -> str:
    if nation_code != 'WW':
        continent_code = pc.country_alpha2_to_continent_code(nation_code)
    else:
        continent_code = 'WW'
    continent_dict = {"NA": "North America","SA": "South America", "AS": "Asia", "AF": "Africa",
        "OC": "Oceania", "EU": "Europe", "AQ": "Antarctica", "WW": "Global"}
    return continent_dict[continent_code]

df_spotify = (df_spotify.with_columns(pl.col('country')
    ## 앞서 정의한 함수를 country 열에 적용
    .map_elements(get_continent_name, return_dtype = pl.String).alias('continent')))
In [2]:
fig = px.box(df_spotify, x = 'continent', y = 'popularity')
fig.show()
In [3]:
fig = px.box((df_spotify. filter(pl.col('country').is_in(["WW", "KR", "US", "BR", "GB", "AU",
"NG"]))), x = 'country', y = 'popularity')
fig.show()
In [4]:
(df_spotify.filter(pl.col('country').is_in(["KR", "GB", "WW", "US"]))
    .group_by('country', 'name').agg(pl.all().sort_by('snapshot_date').first())
    .select(pl.col('country', 'name'), (pl.col('snapshot_date')-pl.col('album_release_date')).
alias('duration'))
    .group_by('country').agg(pl.col('duration').mean().dt.total_days().alias('duration_mean'),
        pl.col('duration').median().dt.total_days().alias('duration_median'))
    .sort('duration_mean', descending = True))
Out[4]:
shape: (4, 3)
countryduration_meanduration_median
stri64i64
"GB"294819
"US"18703
"WW"17224
"KR"6102
In [5]:
fig = px.box((df_spotify.filter(pl.col('country').is_in(["KR", "GB", "WW", "US"]))
        .group_by('country', 'name').agg(pl.all().sort_by('snapshot_date').first())
        .select(pl.col('country', 'name'),
            (pl.col('snapshot_date')-pl.col('album_release_date')).dt.total_days().alias('duration'))),
x = 'country', y = 'duration')
fig.show()
In [6]:
fig = px.box(df_spotify.filter(pl.col('country').is_in(["WW", "KR", "US", "BR", "GB", "AU",
"NG"])), x = 'country', y = 'popularity', color = 'is_explicit')
fig.show()
In [7]:
(df_spotify.filter(pl.col('country').is_in(["WW", "KR", "US", "BR", "GB", "AU", "NG"]))
    .group_by('country').agg(((pl.col('is_explicit')
    .filter(pl.col('is_explicit') == True).len()) / (pl.col('is_explicit').len())*100).round(2).
alias('Explicit_True(%)'),
            ((pl.col('is_explicit').filter(pl.col('is_explicit') == False).len()) / (pl.col('is_explicit')
.len())*100).round(2).alias('Explicit_False(%)'))
    .sort('Explicit_True(%)', descending = True))
Out[7]:
shape: (7, 3)
countryExplicit_True(%)Explicit_False(%)
strf64f64
"US"46.2553.75
"WW"37.3962.61
"AU"33.9266.08
"GB"32.6967.31
"NG"25.9874.02
"BR"25.5574.45
"KR"9.2890.72